﻿// -------------------------------------------------------------------------------------------------------
// LICENSE INFORMATION
//
// - This software is licensed under the MIT shared source license.
// - The "official" source code for this project is maintained at http://mtcagent.codeplex.com
//
// Copyright (c) 2010 OpenNETCF Consulting
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
// associated documentation files (the "Software"), to deal in the Software without restriction, 
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial 
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
// -------------------------------------------------------------------------------------------------------

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using OpenNETCF.Web;
using System.Diagnostics;
using OpenNETCF.IoC;
using System.Xml.Linq;
using System.Threading;

namespace OpenNETCF.MTConnect
{
    public partial class VirtualAgentHandler
    {
        private void HandleGet(HttpContext context)
        {
            var segments = GetRequestPathSegments(context);

            switch (segments.Length)
            {
                case 0:
                    // TODO: this should *get* the current configuration
                    return;
                case 1:
                case 2:
                    if (string.Compare(segments[0], "adapters", true) == 0)
                    {
                        switch (segments.Length)
                        {
                            case 1:
                                ReturnAdaptersInfo(context);
                                return;
                            case 2:
                                ReturnAdapterInfo(context, segments[1]);
                                return;
                        }
                    }
                    break;

            }
            throw new Exception("Invalid command: " + context.Request.Url.PathAndQuery);
        }

        private XElement AdapterAsXml(IHostedAdapter adapter)
        {
            var adapterType = adapter.GetType();

            var element = new XElement(XmlNodeName.Adapter,
                new XAttribute(XmlAttributeName.FullName, adapterType.FullName),
                new XAttribute(XmlAttributeName.Assembly, System.IO.Path.GetFileName(adapterType.Assembly.GetName().CodeBase)),
                new XAttribute(XmlAttributeName.AdapterID, adapter.ID),
                new XAttribute(XmlAttributeName.DeviceID, adapter.Device.ID),
                new XAttribute(XmlAttributeName.AdapterType, adapter.AdapterType)
               );


            var methodsElement = HostedAdapterService.GetAdapterMethodInfos(adapter);
            if (methodsElement != null)
            {
                element.Add(methodsElement);
            }
            return element;
        }

        private XElement AdapterAsXml(Adapter adapter)
        {
            var adapterType = adapter.GetType();

            var element = new XElement(XmlNodeName.Adapter,
                new XAttribute(XmlAttributeName.FullName, adapterType.FullName),
                new XAttribute(XmlAttributeName.Assembly, System.IO.Path.GetFileName(adapterType.Assembly.GetName().CodeBase)),
                new XAttribute(XmlAttributeName.AdapterID, adapter.Device.Name),
                new XAttribute(XmlAttributeName.DeviceID, adapter.Device.ID),
                new XAttribute(XmlAttributeName.AdapterType, adapter.AdapterType)
               );

            return element;
        }

        private void ReturnAdapterInfo(HttpContext context, string adapterID)
        {
            var doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"));

            var adapter = (from a in HostedAdapterService.LoadedAdapters
                           where string.Compare(a.ID, adapterID, true) == 0
                           select a).FirstOrDefault();

            context.Response.ContentType = "text/xml";

            if (adapter != null)
            {
                doc.Add(AdapterAsXml(adapter));
            context.Response.Write(doc.ToString(true));
        }
        }

        private void ReturnAdaptersInfo(HttpContext context)
        {
            var doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"));
            var element = new XElement(XmlNodeName.Adapters,
                new XAttribute(XmlAttributeName.AdaptersPath, HostedAdapterService.AdapterFolder),
                new XAttribute(XmlAttributeName.NewAdaptersPath, HostedAdapterService.NewAdapterFolder)
                );

            List<IHostedAdapter> loadedAdapters = HostedAdapterService.LoadedAdapters.ToList();

            foreach (var adapter in loadedAdapters)
            {
                element.Add(AdapterAsXml(adapter));
            }

            foreach (var adapter in MTConnectProvider.Agent.Adapters)
            {
                if (loadedAdapters.Find(t => t.Device.ID == adapter.Device.ID) == null)
                {
                    element.Add(AdapterAsXml(adapter));
                }
            }

            doc.Add(element);

            context.Response.ContentType = "text/xml";
            context.Response.Write(doc.ToString(true));
        }


        private string GetTargetPath(HttpContext context)
        {
            var path = context.Request.Path;
            var index = path.IndexOf(VirtualAgentRoot, 0, StringComparison.InvariantCultureIgnoreCase);
            if (index < 0)
            {
                throw new Exception("Bad path: " + path);
            }

            return SanitizePath(path.Substring(index + VirtualAgentRoot.Length));
        }

        private string SanitizePath(string path)
        {
            return Uri.UnescapeDataString(path);
        }
    }
}
